home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 11 / Cream of the Crop 11-1.iso / games / nerak2.zip / CONTROL.SCR < prev    next >
Text File  |  1995-09-30  |  57KB  |  1,931 lines

  1. !
  2. ! CONTROL.SCR
  3. !
  4. ! This script manages some independent functions of the game system.  The
  5. ! script is called by the game driver at certain points during game play,
  6. ! and the entry points are numeric (@0, @1, @2..) instead of the usual entry
  7. ! points (@TALK, @GET, ..).
  8. !
  9. ! QUICK SUMMARY OF ENTRY POINTS:
  10. !
  11. ! :@0 - Time Control.         Executed once every minute of game time.
  12. !                             (See 'MOVES_PER_MINUTE' parameter)
  13. !
  14. ! :@1 - PLAYER MOVES          Invoked for each PLAYER during a FIGHT
  15. !
  16. ! :@2 - MONSTER MOVES         Invoked once to move every monster at
  17. !                             once during a fight (not once for each
  18. !                             monster)
  19. !
  20. ! :@3 - Keyboard/Mouse Event. Called every time a KEY is pressed or a mouse
  21. !                             button clicked during normal game play.
  22. !
  23. ! :@4 - POSITION MONSTER      Invoked once to position the NPCs for
  24. !                             a fight before MONSTER MOVES is called
  25. !                             for the first time.
  26. !
  27. !---------------------------------------------------------------------------!
  28. :@0 ! Entry Point @0 : Time Control Script                                  !
  29. !---------------------------------------------------------------------------!
  30. !
  31. ! This script will start execution at this label once per 'minute' during
  32. ! regular play.  The variable GROUP.MOVES contains the total number of
  33. ! moves the party has made since the begining of the game.  A minute is
  34. ! defined by the current value of the variable 'MovesPerMinute'
  35. !
  36. ! Time is controled by seting the following variables from any script:
  37. !
  38. !   Variable             Default  Description
  39. !   -------------------  -------  --------------------------------
  40. !   MovesPerMinute             2  # of moves per game 'minute'
  41. !   MinutesInAnHour           60  # of minutes in an game 'hour'
  42. !   HoursInADay               24  # of hour in a game 'day'
  43. !   DaysInAMonth              30  # of days in a game 'month'
  44. !   MonthsInAYear             12  # of months in a game 'year'
  45. !   
  46. ! The CURRENT time is obtained (and modified) by setting the following
  47. ! variables:
  48. !
  49. !   year                 Current Year   (Range -32767 to 32767)
  50. !   month                Current Month  (Range 0 to MonthsInAYear - 1)
  51. !   day                  Current Day    (Range 0 to DaysInAMonth  - 1)
  52. !   hour                 Current Hour   (Range 0 to HoursInADay   - 1)
  53. !   minute               Current Minute (Range 0 to MinutesInADay - 1)
  54. !
  55.  
  56. ! Update the clock, one more minute has passed !
  57.  
  58.   gosub CLOCK_TICK;
  59.   if minute = 0 gosub CLOCK_PRINT;
  60.  
  61. ! No perform some time dependent actions
  62. ! First, save our original status just in case we need it later..
  63.   L255 = group.current; ! Save current party spokesperson   !
  64.   L254 = FALSE;         ! Have NOT created a random monster !
  65.  
  66. ! THINGS TO DO EVERY MINUTE  
  67.   if group.energy > 0 then
  68.     dec( group.energy );
  69.     ! In the desert, during the day, you consume energy twice as fast
  70.     if world.density(L0,L1) = DESERT and group.vehicle.count = 0 then
  71.       if hour > sunrise and hour < sunset then
  72.         dec( group.energy ); 
  73.       endif;
  74.     endif;
  75.     if L2 = SWAMP and group.vehicle.count = 0 then 
  76.       if random(5) = 0 then ! one out of 5 !
  77.         L255 = group.current;
  78.         foreach player do
  79.           if not player.poisoned then
  80.             player.poisoned = (random(3) = 0); ! one out of 3 !
  81.             if player.poisoned then
  82.               writeln( player.name, " got poisoned by swamp gas!" );
  83.             endif;
  84.           endif;
  85.         endfor;
  86.         group.current = L255; ! Restore the current spokesperson !
  87.       endif;
  88.     endif;
  89.   endif;
  90.   
  91. ! THINGS TO DO ONCE AN HOUR
  92. if minute = 0 then 
  93.   ! Create a random monster 1 out of every 5 times (approx) !
  94.   if random(5) = 0 then
  95.     if world.type = OUTDOORS or world.type = DUNGEON or world.type = HAUNTED then
  96.       gosub NEWMONSTER;
  97.     endif;
  98.   endif;
  99.  
  100.   ! Check to see if you have food.. !
  101.   if group.food <= group.size then
  102.     if group.food = 0 then
  103.       writeln( "You have no food.." );
  104.     else
  105.       writeln( "You are running out of food.." );
  106.     endif;
  107.   endif;
  108. endif;
  109.  
  110. ! Every quarter of an hour !
  111. L25 = max(MinutesInAnHour / 4 + 1,2);
  112. if minute % L25 = 0 then
  113.   ! Group must rest within 2 hours or start suffering damage !
  114.   if group.energy < MinutesInAnHour * 2 then 
  115.     if group.energy > 0 then
  116.       writeln( "You must rest soon.." );
  117.     else
  118.       writeln( "You are exhausted.." );
  119.     endif;
  120.   endif;
  121.   ! Check for poison, hunger and exhaustion !
  122.   foreach player do
  123.     if player.hp > 0 then
  124.       if player.poisoned then
  125.         s0 = "poisoning";
  126.         gosub HITPLAYER;
  127.       elsif player.energy = 0 and group.food = 0 then
  128.         s0 = "hunger";
  129.         gosub HITPLAYER;
  130.       elsif group.energy <= 0 then
  131.         s0 = "exhaustion";
  132.         gosub HITPLAYER;
  133.       endif;
  134.     endif;
  135.   endfor;
  136. endif;
  137.  
  138. !
  139. ! The following controls healing and recovery of power.  You can
  140. ! change the rate of healing by using a different value, but remember
  141. ! that the power heal value (8 below) should be a MULTIPLE of the
  142. ! first number (4) or it will not work.
  143. !
  144. if minute % 4 = 0 and group.energy > 0 then
  145.   foreach player do
  146.     if group.food or player.energy then
  147.       gosub HEAL_HP;
  148.       ! Every 8 (twice as slow) restore power
  149.       if minute % 8 = 0 then
  150.         gosub HEAL_PWR;
  151.       endif;
  152.     endif;
  153.   endfor;
  154. endif;
  155.  
  156. ! Go back with same selected spokesperson.. !
  157. group.current = L255;
  158. CONTINUE;
  159.  
  160. !---------------------------------------------------------------------------!
  161. :@1 ! PLAYER MOVES DURING A FIGHT
  162. !---------------------------------------------------------------------------!
  163. !
  164.   frame(player.x,player.y,SYS_FRAME);
  165.   write( player.name, " - " );
  166.   if player.hp < 2 then
  167.     if player.hp = 1 then writeln( "is unconscious!" );
  168.                      else writeln( "is dead!" ); 
  169.     endif;
  170.   elsif player.paralyzed then 
  171.     writeln( "is paralyzed!" );
  172.   elsif player.scared then
  173.     writeln( "is scared!" );
  174.   else
  175.     stats(player);
  176.     keypress = GET_ACTION;
  177.     frame(player.x,player.y,-SYS_FRAME);
  178.     goto :@3;
  179.   endif;
  180.   frame(player.x,player.y,-SYS_FRAME);
  181.   STOP;
  182.  
  183. !---------------------------------------------------------------------------!
  184. :@2 ! Move NPCs during a fight
  185. !---------------------------------------------------------------------------!
  186.   runscript( "FIGHTING", 1 );
  187.   stop;
  188.  
  189. !---------------------------------------------------------------------------!
  190. :@4 ! Position NPCs before a fight
  191. !---------------------------------------------------------------------------!
  192.   runscript( "FIGHTING", 0 );
  193.   stop;
  194.  
  195. !---------------------------------------------------------------------------!
  196. :@3 ! Keyboard Map Entry Point : Process a key press
  197. !---------------------------------------------------------------------------!
  198.  
  199. !
  200. ! THE FOLLOWING TABLE IS A SHORT LIST OF THE VALUES ASSOCIATED WITH EACH
  201. ! KEY. NOTE THAT SPECIAL KEYS HAVE BEEN MAPPED TO DISTINCT NUMBERS TO 
  202. ! AVOID USING THE WIERD PC KEY VALUES.
  203.  
  204. ! CTRL +A to Z    =   1 to  26
  205. ! ESCape key      =  27
  206. ! space           =  32
  207. ! 0-9             =  48 to  57
  208. ! A-Z             =  65 to  90 
  209. ! a-z             =  65 to  90 (i.e. NO LOWERCASE)
  210. ! F1 - F10        = 131 to 140
  211. ! Shift+F1 - F10  = 141 to 150
  212. ! Ctrl +F1 - F10  = 151 to 160
  213. ! ALT  +F1 - F10  = 161 to 170
  214. ! ALT  +1 to 10   = 171 to 180
  215. ! ALT  +A to Z    = 201 to 226
  216. !
  217. ! KEY PAD VALUES (arrow keys!):
  218. ! HOME            = 190        ! CTRL + HOME     = 187
  219. ! END             = 191        ! CTRL + END      = 186
  220. ! UP              = 192        ! CTRL + UP       = 230
  221. ! DOWN            = 193        ! CTRL + DOWN     = 231
  222. ! LEFT            = 194        ! CTRL + LEFT     = 184
  223. ! RIGHT           = 195        ! CTRL + RIGHT    = 185
  224. ! PGUP            = 196        ! CTRL + PGUP     = 189
  225. ! PGDN            = 197        ! CTRL + PGDN     = 188 
  226. ! INS             = 198
  227. ! DEL             = 199
  228. !
  229. ! When you use the mouse to click on something, the variable BUTTON
  230. ! contains which button you clicked (1=Left, 2=Right, 3=Middle), and
  231. ! the rest of the information is obtained as follos:
  232. !
  233. ! VALUE OF KEYPRESS Value of POINTX      Value of POINTY
  234. ! ----------------- ------------------   ------------------
  235. ! VIEW_CLICK 235    World X coordinate   World Y coordinate
  236. ! MENU_CLICK 236    Menu Offset          Menu Choice (0 to n)
  237. ! ICON_CLICK 237    0-7 icon position    0-n block # in blocks file
  238. ! STAT_CLICK 238    6 (group was shown)  Member selected 1-6
  239. !                   0-5 (member shown)   Clicked Item:
  240. !                                        0 = no particular place
  241. !                                        1 = worn weapon location
  242. !                                        2 = worn shield location
  243. !                                        3 = worn armor  location
  244. !                                        4 = worn staff  location
  245. !                                        5 = worn ring   location
  246. !                                        6 = worn amulet location
  247. !                                        7 = Item #  1 in backpack
  248. !                                        8 = Item #  2 in backpack
  249. !                                          .... 
  250. !                                       22 = Item # 16 in backpack
  251. !
  252.   if KEYPRESS = 27 then
  253.     if fighting then
  254.       writeln( "Trying to escape.." );
  255.       fight( STOP );
  256.     endif;
  257.   endif;
  258.   if KEYPRESS >= 65 and KEYPRESS <= 90 then
  259.     on KEYPRESS - 65 goto 
  260.       LETTER_A, LETTER_B, LETTER_C, LETTER_D, LETTER_E,
  261.       LETTER_F, LETTER_G, LETTER_H, LETTER_I, LETTER_J,
  262.       LETTER_K, LETTER_L, LETTER_M, LETTER_N, LETTER_O,
  263.       LETTER_P, LETTER_Q, LETTER_R, LETTER_S, LETTER_T,
  264.       LETTER_U, LETTER_V, LETTER_W, LETTER_X, LETTER_Y, LETTER_Z;
  265.   endif;
  266.   if KEYPRESS >= 48 and KEYPRESS <= 57 then
  267.     on KEYPRESS - 48 goto
  268.       DIGIT_0, DIGIT_1, DIGIT_2, DIGIT_3, DIGIT_4,
  269.       DIGIT_5, DIGIT_6, DIGIT_7, DIGIT_8, DIGIT_9;
  270.   endif;
  271.   if KEYPRESS = 32 goto SPACE;
  272.   ! KEYPAD ARROWS !
  273.   if KEYPRESS >= 190 and KEYPRESS <= 197 then
  274.     on KEYPRESS - 190 goto
  275.      MOVE_UL, MOVE_DL, MOVE_UP, MOVE_DN, MOVE_LF, MOVE_RT, MOVE_UR, MOVE_DR;
  276.   endif;
  277.   if KEYPRESS >= 235 and KEYPRESS <= 240 then
  278.     on KEYPRESS - 235 goto
  279.        VIEW_CLICK, MENU_CLICK, ICON_CLICK, STAT_CLICK;
  280.   endif;
  281.   ! F1 - F10        = 131 to 140
  282.   if keypress >= 131 and keypress <= 140 then
  283.     on keypress - 131 goto FKEY1,FKEY2,FKEY3,FKEY4,FKEY5,FKEY6,FKEY7,FKEY8,FKEY9,FKEY10;
  284.   endif;
  285.  
  286.   ! Not handled by the script. The driver takes the default action !
  287.   CONTINUE;
  288.  
  289. :DIGIT_0
  290.   STATS(-2); ! Display GROUP statistics !
  291.   STOP;
  292.  
  293. :DIGIT_1 :DIGIT_2 :DIGIT_3 :DIGIT_4 :DIGIT_5 :DIGIT_6
  294.   GROUP.CURRENT = KEYPRESS - 49; ! Use 0 to 5 instead of 1 to 6  !
  295.   STATS( GROUP.CURRENT );        ! Display INDIVIDUAL statistics !
  296.   STOP;
  297.  
  298. :DIGIT_7
  299.   STOP;
  300.  
  301. :DIGIT_8
  302.   STOP;
  303.  
  304. :DIGIT_9
  305.   STOP;
  306.  
  307. :LETTER_A
  308.   write( "Attack: " );
  309.   L3 = locate;
  310.   if failure then
  311.     goto NOTHING;
  312.   endif;
  313.   if npc.count then ! Attack a character !
  314.     writeln( npc.class );
  315.     if fighting then
  316.       goto ATTACK_NPC; ! if we ARE fighting, go do it.. !
  317.     else
  318.       if npc.type <> HOSTILE then
  319.         writeln( "Find some bad guys to fight!" );
  320.         STOP;
  321.       endif;
  322.     endif;
  323.     FIGHT; ! START FIGHT MODE. SCRIPT EXECUTION ENDS HERE !
  324.   endif;
  325.   if object.count then
  326.     if object.type = CHEST then
  327.       if object.locktype then
  328.         writeln( "Instead of fighting it, try 'UNLOCK'!" );
  329.       else
  330.         writeln( "It's not even locked, why fight it?" );
  331.       endif;
  332.     else
  333.       writeln( "Why would you want to fight the ", object.name );
  334.     endif;
  335.   endif;
  336.   STOP;
  337.  
  338. :LETTER_B
  339.   STOP;
  340.  
  341. !------------------------------------------------------------------------!
  342. :LETTER_C  ! CAMP OUT !
  343. !
  344. ! First, all temporary magical effects are eliminated by reducing any 
  345. ! attribute that exceeds the maximum value for the same attribute.
  346. !
  347. ! Armor, Shields, Rings and Amulets re-apply their effect (if any).
  348. !
  349. ! The group rests for a third of a day, in one hour increments.  For
  350. ! each hour rested, the group gains 4 hours of 'wake-up' energy.  This
  351. ! means the group should be able to go one and a third days without 
  352. ! sleep.
  353. !
  354. ! Random monsters may appear, but not too often.
  355. !
  356.   if fighting then
  357.     writeln( "This is not a good time to rest.." );
  358.     stop;
  359.   endif;
  360.   frame( group.x, group.y, 10 ); ! ZZZZ.... !
  361.   write( "Resting" );
  362.   voice( "snore", 1000 );
  363.   L255 = group.current; ! Save current party spokesperson   !
  364.   L254 = FALSE;         ! Have NOT created a random monster !
  365.   foreach player do
  366.     gosub NEW_LEVEL; ! Figure out if character went up one level !
  367.     write(".");
  368.     ! First, get rid of temporary magical increases in attributes !
  369.     player.str = min(player.str,player.mstr);
  370.     player.aim = min(player.aim,player.maim);
  371.     player.dex = min(player.dex,player.mdex);
  372.     player.spd = min(player.spd,player.mspd);
  373.     player.pwr = min(player.pwr,player.mpwr);
  374.     player.hp  = min(player.hp, player.mhp);
  375.     player.iq  = min(player.iq, player.miq);
  376.     player.ac  = min(player.ac, player.mac);
  377.     if player.armor.count or player.shield.count then
  378.       if player.armor.cursed or player.shield.cursed then
  379.         player.ac = 0;
  380.       else
  381.         inc( player.ac, player.armor.ac + player.shield.ac );
  382.       endif;
  383.     endif;
  384.     if player.ring.count and player.ring.charges then
  385.       curritem = player.ring;
  386.       gosub M1_INVOKE;
  387.     endif;
  388.     if player.amulet.count and player.amulet.charges then
  389.       curritem = player.amulet;
  390.       gosub M1_INVOKE;
  391.     endif;
  392.   endfor;
  393.   ! # of hours to rest is one third of a day !
  394.   for L253 = 1 to HoursInADay / 3 + 1 do 
  395.     write(".");
  396.     ! Each hour of sleep gives 4 hours of energy !
  397.     if group.energy + MinutesInAnHour * 4 > 32767 then
  398.       group.energy = 32767;
  399.     else
  400.       inc( group.energy, MinutesInAnHour * 4 );
  401.     endif;
  402.     for L252 = 0 to MinutesInAnHour / 2 do
  403.       gosub CLOCK_TICK;
  404.       gosub CLOCK_TICK;
  405.       foreach player do
  406.        if group.food or player.energy then
  407.           gosub HEAL_HP;
  408.           if L252 % 2 then
  409.             gosub HEAL_PWR;
  410.           endif;
  411.         endif;
  412.       endfor;
  413.     endfor;
  414.     ! Check to see if random monsters appear !
  415.     if world.type = OUTDOORS or world.type = DUNGEON or world.type = HAUNTED then
  416.       if random(17) = 0 then
  417.         gosub NEWMONSTER;
  418.         if L254 then
  419.           frame( group.x, group.y, -1 ); ! Restore !
  420.           writeln( "You wake up under attack.." );
  421.           FIGHT;       ! Wake up and fight.. !
  422.         endif;
  423.       endif;
  424.     endif;
  425.   endfor;
  426.   group.current = L255; ! Go back to original spokes person !
  427.   frame( group.x, group.y, -1 ); ! Restore !
  428.   voice( "CHIMES", 1000 );
  429.   gosub CLOCK_PRINT;
  430.   STOP;
  431.  
  432. :LETTER_D
  433.   write( "Drop " );
  434.   L0 = select$n( player );
  435.   stats(-1);
  436.   if L0 >= 0 then
  437.     writeln( player.bp.name );
  438.     runscript( player.bp.script, "CURRITEM", DROP );
  439.     ! Does NOT return !
  440.   endif;
  441.   writeln( "nothing.." );
  442.   if L0 < -1 then
  443.     writeln( "You are not carrying anything!" );
  444.   endif;
  445.   STOP;
  446.  
  447. :LETTER_E
  448.   if group.vehicle.count then ! Must be on foot !
  449.     writeln( "You must be on foot to enter/exit worlds.." );
  450.     STOP;
  451.   endif;
  452.   if group.x <> 0 or group.y <> 0 then
  453.     for L0 = 0 to 31 do
  454.       if world.doorx(L0) = group.x and world.doory(L0) = group.y then
  455.         world.door = L0; ! Use this door !
  456.         writeln( "Please wait..." );
  457.         runscript( WORLD, "WORLDDEF", EXIT );
  458.         ! Should not return !
  459.       endif;
  460.     endfor;
  461.   endif;
  462.   writeln( "There is no door here.." );
  463.   STOP;
  464.  
  465. :LETTER_F
  466.   STOP;
  467.  
  468. :LETTER_G
  469.   ! Get !
  470.   if player.hp > 1 then
  471.     write( "Get " );
  472.     L0 = locate( object ); ! Find OBJECT only, no people !
  473.     if success then 
  474.       writeln( object.type );
  475.       if L0 < 2 then
  476.         runscript( object.script, "OBJECT", GET );
  477.         ! Does NOT return !
  478.       else
  479.         writeln( "You can't reach the ", object.type );
  480.       endif;
  481.     else
  482.       goto NOTHING;
  483.     endif;
  484.   else
  485.     write( player.name, " can't get anything.." );
  486.   endif;
  487.   STOP;
  488.  
  489. :LETTER_H  
  490.   STOP;
  491.  
  492. :LETTER_I
  493.   display$n( player );
  494.   STOP;
  495.  
  496. :LETTER_J
  497.   STOP;
  498.  
  499. :LETTER_K
  500.   STOP;
  501.  
  502. :LETTER_L
  503.   write( "Look at " );
  504.   L0 = locate; ! Find ANYTHING !
  505.   if success then 
  506.     if npc.count then ! Found an NPC !
  507.       writeln( npc.type );
  508.       runscript( npc.script, "OBJECT", LOOK );
  509.     endif;
  510.     writeln( object.type );
  511.     runscript( object.script, "OBJECT", LOOK );
  512.   endif;
  513.   goto NOTHING;
  514.  
  515. :LETTER_M
  516.   STOP;
  517.  
  518. :LETTER_N
  519.   write( "Invoke " );
  520.   L0 = select$n( player, SCROLL, GEMS );
  521.   stats(-1);
  522.   if L0 >= 0 then
  523.     runscript( player.bp.script, "CURRITEM", INVOKE );
  524.     ! Does NOT return !
  525.   endif;
  526.   writeln( "nothing .." );
  527.   if L0 < -1 then
  528.     writeln( "You have no items that you can invoke.." );
  529.   endif;
  530.   STOP;
  531.  
  532. :LETTER_O
  533.   STOP;
  534.  
  535. :LETTER_P
  536.   STOP;
  537.  
  538. :LETTER_Q
  539.   write( "Quaff (eat or drink) " );
  540.   L0 = select$n( player, FOOD, POTION );
  541.   stats(-1);
  542.   if L0 >= 0 then
  543.     runscript( player.bp.script, "CURRITEM", INVOKE );
  544.     ! Does NOT return !
  545.   endif;
  546.   writeln( "nothing .." );
  547.   if L0 < -1 then
  548.     writeln( "You have no items that you can eat or drink" );
  549.   endif;
  550.   STOP;
  551.  
  552. :LETTER_R
  553.   write( "Remove " );
  554.   L0 = select( player.body ); ! Any worn item !
  555.   stats(-1);
  556.   if L0 >= 0 then
  557.     runscript( player.body.script, "CURRITEM", REMOVE );
  558.   endif;
  559.   writeln( "nothing.." );
  560.   if L0 < -1 then
  561.     writeln( "You have no items to remove!" );
  562.   endif;
  563.   STOP;
  564.  
  565. :LETTER_S
  566.   runscript( player.script, "CASTING", CAST );
  567.   STOP;
  568.  
  569. :LETTER_T
  570.   write( "Talk to " );
  571.   L0 = locate; ! Find ANYTHING !
  572.   if success then 
  573.     if npc.count then ! Found an NPC !
  574.       if abs(npc.x - player.x) > 2 or abs(npc.y - player.y) > 2 then
  575.         writeln( "You must get closer!" );
  576.         STOP;
  577.       endif;
  578.       writeln( npc.type );
  579.       runscript( npc.script, "OBJECT", TALK );
  580.     endif;
  581.     if abs(object.x - player.x) > 2 or abs(object.y - player.y) > 2 then
  582.       writeln( "You must get closer!" );
  583.       STOP;
  584.     endif;
  585.     writeln( object.type );
  586.     runscript( object.script, "OBJECT", TALK );
  587.   endif;
  588.   if group.x = pointx and group.y = pointy then
  589.     writeln( "yourself..?" );
  590.   else
  591.     writeln( "no one.." );
  592.   endif;
  593.   STOP;
  594.  
  595. :LETTER_U
  596.   write( "Use " );
  597.   L0 = locate( OBJECT ); ! Find an object !
  598.   if success then 
  599.     if abs(object.x - player.x) > 2 or abs(object.y - player.y) > 2 then
  600.       writeln( "You must get closer!" );
  601.       STOP;
  602.     endif;
  603.     writeln( object.type );
  604.     runscript( object.script, "OBJECT", USE );
  605.   endif;
  606.   goto NOTHING;
  607.  
  608. :LETTER_V
  609.   if group.size > 1 then
  610.     writeln( "Who leaves the party?" );
  611.     L0 = select( group );
  612.     stats(-1);
  613.     if player.index = 0 then
  614.       writeln( "You can't leave the party!" );
  615.       STOP;
  616.     endif;
  617.     if player.hp = 0 then
  618.       writeln( "You leave ", player.name, "'s body to the vultures.." );
  619.     elsif player.hp < 2 then
  620.       writeln( "You abandon ", player.name, ", who is almost dead.." );
  621.     else
  622.       writeln( player.name, " leaves the group." );
  623.     endif;
  624.     LEAVE(player.index);
  625.     stats(-1);
  626.   else
  627.     writeln( "You are alone!" );
  628.   endif;
  629.   STOP;
  630.  
  631. :LETTER_W
  632.  
  633.   write( "Wear (or Wield) " );
  634.   L0 = select$n( player, WEAPON, ARMOR, RING, AMULET, STAFF );
  635.   stats(-1);
  636.   if L0 >= 0 then
  637.     runscript( player.bp.script, "CURRITEM", WEAR );
  638.     ! Does NOT return !
  639.   endif;
  640.   writeln( "nothing .." );
  641.   if L0 < -1 then
  642.     writeln( "You have no items that you can wear or wield" );
  643.   endif;
  644.   STOP;
  645.  
  646. :LETTER_X
  647.   if group.vehicle.count then
  648.     ! We are riding on a vehicle !
  649.     curritem = group.vehicle;
  650.     runscript( group.vehicle.script, "CURRITEM", EXIT );
  651.   else
  652.     writeln( "You are already on foot!" );
  653.   endif;
  654.   STOP;
  655.  
  656. :LETTER_Y
  657.   STOP;
  658.  
  659. :LETTER_Z
  660.   if player.staff.count then
  661.     curritem = player.staff;
  662.     runscript( player.staff.script, "CURRITEM", invoke );
  663.   endif;
  664.   STOP;
  665.  
  666. :NOTHING
  667.   if group.x = pointx and group.y = pointy then
  668.     writeln( "yourself..?" );
  669.   else
  670.     writeln( "nothing.." );
  671.   endif;
  672.   STOP;
  673.  
  674. :SPACE
  675.   writeln( "Pass.." );
  676.   goto @0; ! Time Control !
  677.  
  678. :VIEW_CLICK
  679.   ! Did we click on ourselves? !
  680.   if group.x = pointx and group.y = pointy then
  681.     writeln( "Don't do that! It tickles.." );
  682.     STOP;
  683.   endif;
  684.   ! First, check the objects !
  685.   L2 = locate( object, pointx, pointy );
  686.   if success then
  687.     if button = 1 then
  688.       if abs(pointx - player.x) > 1 or abs(pointy - player.y) > 1 then
  689.         writeln( "You can't reach the ", object.type );
  690.         STOP;
  691.       endif;
  692.       if object.type = VEHICLE or object.type = DOOR or
  693.          object.type = SIGN    or
  694.          object.type = CHEST and object.locktype > 0 then
  695.         writeln( "Use ", object.type );
  696.         runscript( object.script, "OBJECT", USE );
  697.       else
  698.         writeln( "Get ", object.type );
  699.         runscript( object.script, "OBJECT", GET );
  700.       endif;
  701.     elsif button = 2 then
  702.       writeln( "Look at ", object.type );
  703.       runscript( object.script, "OBJECT", LOOK );
  704.     else
  705.       writeln( "The middle button has no effect!" );
  706.       stop;
  707.     endif;
  708.   endif;
  709.   ! Next check the characters !
  710.   L2 = locate( npc, pointx, pointy );
  711.   if success then
  712.     if button = 1 then
  713.       if abs(pointx - player.x) > 2 or abs(pointy - player.y) > 2 then
  714.         writeln( "You must get nearer for conversation." );
  715.         STOP;
  716.       endif;
  717.       writeln( "Talk to ", npc.type );
  718.       runscript( npc.script, "OBJECT", TALK );
  719.     elsif button = 2 then
  720.       writeln( "Look at ", npc.type );
  721.       runscript( npc.script, "OBJECT", LOOK );
  722.     else
  723.       writeln( "The middle button has no effect!" );
  724.     endif;
  725.   endif;
  726.   STOP;
  727.  
  728. :MENU_CLICK
  729.   ! I don't do anything with this right now.. !
  730.   STOP;
  731.  
  732. :ICON_CLICK
  733.   on pointx goto
  734.     LETTER_A,  ! Attack !
  735.     LETTER_G,  ! Get !
  736.     LETTER_D,  ! Drop !
  737.     LETTER_L,  ! Look !
  738.     LETTER_T,  ! Talk !
  739.     LETTER_C,  ! Camp Out or Sleep !
  740.     LETTER_E,  ! Enter or Exit through a door !
  741.     LETTER_I;  ! INVENTORY !
  742.   STOP;
  743.  
  744. :STAT_CLICK
  745.   if pointx = 6 and pointy < group.size then
  746.     ! Looking at Group, selected an individual !
  747.     GROUP.CURRENT = pointy;
  748.     STATS( GROUP.CURRENT );        ! Display INDIVIDUAL statistics !
  749.   else
  750.     ! Looking at Individual (point x), clicked at item)
  751.     on pointy goto 
  752.       SHOW_GRP,    ! No item, so go back to showing the GROUP
  753.       SHOW_WPN,    ! Clicked at weapon being worn (or empty place)
  754.       SHOW_SHLD,   ! Clicked at shield being worn (or empty place)
  755.       SHOW_ARMR,   ! Clicked at armor being worn (or empty place)
  756.       SHOW_STF,    ! Clicked at staff being worn (or empty place)
  757.       SHOW_RING,   ! Clicked at ring being worn (or empty place)
  758.       SHOW_AMULET; ! Clicked at amulet being worn (or emtpy place)
  759.     ! No, Clicked at item in the back pack !
  760.     if pointy > 6 and pointy < 22 then
  761.       setbp( player, pointy - 7 );
  762.       gosub DO_BP_ITEM;
  763.     endif;
  764.   endif;
  765.   STOP;
  766.  
  767. :SHOW_GRP
  768.   stats(6); STOP;
  769.  
  770. :SHOW_WPN
  771.   if player.weapon.count then
  772.     curritem = player.weapon;
  773.     gosub DO_WORN_ITEM;
  774.   endif;
  775.   STOP;
  776.  
  777. :SHOW_SHLD
  778.   if player.shield.count then
  779.     curritem = player.shield;
  780.     gosub DO_WORN_ITEM;
  781.   endif;
  782.   STOP;
  783.  
  784. :SHOW_ARMR
  785.   if player.armor.count then
  786.     curritem = player.armor;
  787.     gosub DO_WORN_ITEM;
  788.   endif;
  789.   STOP;
  790.  
  791. :SHOW_STF
  792.   if player.staff.count then
  793.     curritem = player.staff;
  794.     gosub DO_WORN_ITEM;
  795.   endif;
  796.   STOP;
  797.  
  798. :SHOW_RING
  799.   if player.ring.count then
  800.     curritem = player.ring;
  801.     gosub DO_WORN_ITEM;
  802.   endif;
  803.   STOP;
  804.  
  805. :SHOW_AMULET
  806.   if player.amulet.count then
  807.     curritem = player.amulet;
  808.     gosub DO_WORN_ITEM;
  809.   endif;
  810.   STOP;
  811.  
  812. :DO_WORN_ITEM
  813.   if button = 1 then
  814.     writeln( "Remove ", curritem.type, ".." );
  815.     runscript( curritem.script, "CURRITEM", REMOVE );
  816.   elsif button = 2 then
  817.     writeln( "Look at ", curritem.type );
  818.     runscript( curritem.script, "CURRITEM", LOOK );
  819.   endif;
  820.   return;
  821.  
  822. :DO_BP_ITEM
  823.   if player.bp.count then
  824.     curritem = player.bp;
  825.     if button = 1 then
  826.       if curritem.type = WEAPON or curritem.type = ARMOR or
  827.          curritem.type = RING   or curritem.type = AMULET or
  828.          curritem.type = SHIELD or curritem.type = STAFF then
  829.          writeln( "Wear/Wield ", curritem.type, ".." );
  830.          runscript( curritem.script, "CURRITEM", WEAR );
  831.       else
  832.          writeln( "Use ", curritem.type, ".." );
  833.          runscript( curritem.script, "CURRITEM", USE );
  834.       endif;
  835.     elsif button = 2 then
  836.       writeln( "Look at ", curritem.type );
  837.       runscript( curritem.script, "CURRITEM", LOOK );
  838.     endif;
  839.   endif;
  840.   return;
  841.  
  842. !---------------------------------------------------------------------------!
  843. !---------------------------------------------------------------------------!
  844. !---------------------------------------------------------------------------!
  845. !---------------------------------------------------------------------------!
  846. !---------------------------------------------------------------------------!
  847. !
  848. ! SUBROUTINE: HEAL_HP
  849. !
  850. ! Heal the players with the passage of time
  851. !
  852. :HEAL_HP
  853.   ! alive and not sick !
  854.   if player.hp > 0 and not player.poisoned then
  855.     dec( player.energy );
  856.     if player.energy <= 0 then
  857.       if group.food > 0 then
  858.         dec( group.food );
  859.         player.energy = 255;
  860.       else
  861.         writeln( player.name, " goes hungry!" );
  862.         return;
  863.       endif;
  864.     endif;
  865.     if player.hp < player.mhp then
  866.       inc( player.hp );
  867.     endif;
  868.   endif;
  869.   return;
  870.  
  871. !
  872. ! SUBROUTINE: HEAL_PWR
  873. !
  874. ! Restore magic points withthe passage of time..
  875. !
  876. :HEAL_PWR
  877.   if player.hp > 0 and player.energy > 0 and player.pwr < player.mpwr then
  878.     inc( player.pwr );
  879.     if player.class = ELF and player.pwr < player.mpwr then
  880.       inc( player.pwr ); ! Do elves faster.. !
  881.     endif;
  882.   endif;
  883.   return;
  884.  
  885. !
  886. ! SUBROUTINE to create a Random Monster
  887. !
  888. :NEWMONSTER
  889.   ! Try to find a position for the monster up to 8 times..
  890.   for L3 = 1 to 8 do
  891.     L0 = group.x + random(8) - 4;
  892.     L1 = group.y + random(8) - 4;
  893.     if L0 < 0 then L0 = 0; endif;
  894.     if L1 < 0 then L1 = 0; endif;
  895.     if L0 >= world.x then L0 = world.x - 1; endif;
  896.     if L1 >= world.y then L1 = world.y - 1; endif;
  897.     if L0 <> player.x or L1 <> player.y then
  898.       L2 = world.density(L0,L1);
  899.       if L2 = FLAT or L2 = ROUGH or L2 = VERY_ROUGH or L2 = SWAMP or L2 = DESERT then
  900.         ! Create a LAND-BASED monster !
  901.         L2 = random(3);    ! Small, Medium or Large (0-2) !
  902.         L3 = random(L2+3); ! Select a graphics block for that size (0-4) !
  903.         if world.type = DUNGEON then
  904.           L4 = DEFCAVEBLK( L3 );            ! Leader   !
  905.           L5 = DEFCAVEBLK( random(L3+1) );  ! Follower !
  906.           L6 = CAVE_MONSTER;
  907.         elsif world.type = HAUNTED then
  908.           L4 = DEFSPOOKBLK( L3 );           ! Leader   !
  909.           L5 = DEFSPOOKBLK( random(L3+1) ); ! Follower !
  910.           L6 = SPOOK_MONSTER;
  911.         else
  912.           ! OUTDOORS or ARENA !
  913.           L4 = DEFLANDBLK( L3 );            ! Leader   !
  914.           L5 = DEFLANDBLK( random(L3+1) );  ! Follower !
  915.           L6 = LAND_MONSTER;
  916.         endif;
  917.         goto DOIT;
  918.       elsif L2 = DEEP_WATER then
  919.         ! Create a WATER-BOUND monster !
  920.         L2 = random(3);        ! Small, Medium, Large (0-2) !
  921.         if random(5) = 0 then  ! Pirate Ship (SPECIAL CASE) !
  922.           L4 = DEFWATERBLK(4); ! Fifth water monster is a ship !
  923.           L5 = DEFWATERBLK(4); ! Followers are ships also !
  924.         else
  925.           L3 = random(L2+2); ! Select a graphics block for that size (0-3) !
  926.           L4 = DEFWATERBLK( L3 );            ! Leader   !
  927.           L5 = DEFWATERBLK( random(L3+1) );  ! Follower !
  928.         endif;
  929.         L6 = WATER_MONSTER;
  930.         goto DOIT;
  931.       endif;
  932.     endif;
  933.   endfor;
  934.   return; ! Tried 8 Times, give up !
  935.  
  936. :DOIT
  937.   new(npc,L0,L1,L4);
  938.   npc.type   = HOSTILE;       ! NPC Type
  939.   npc.stats  = defstat(L2);   ! Statistics Record
  940.   npc.block2 = L5;            ! Followers (if any)
  941.   npc.class  = L6;            ! Monster Class
  942.  
  943.   ! Gold carried
  944.   if world.type = ARENA then
  945.     npc.value = random(50)+1; ! Very little money (Up to 5 gold pieces) !
  946.   else
  947.     npc.value = 0;
  948.   endif;
  949.  
  950.   !
  951.   ! # of monsters in the group.  The formula is based on L2 (monster size).
  952.   ! If small  (L2=0), then # = random( group.size + 6 ) + 1
  953.   ! If medium (L2=1), then # = random( group.size + 3 ) + 1
  954.   ! if large  (L2=2), then # = random( group.size ) + 1
  955.   npc.count = random( group.size + (2 - L2) * 3 ) + 1;
  956.  
  957.   L254 = TRUE; ! Monster has been created !
  958.  
  959.   voice( "ALERT", 1000 );
  960.   return;
  961.  
  962. !
  963. ! This SUBROUTINE will hit every player in the group by using the
  964. ! subroutine HITPLAYER.
  965. !
  966. :HITGROUP
  967.   foreach player do
  968.     gosub HITPLAYER;
  969.   endfor;
  970.   return;
  971.  
  972. !
  973. ! This SUBROUTINE will decrement the hit points of the current
  974. ! group member.  It checks to see if the player has died or lost
  975. ! consciousnes.  The variable S0 contains the reason for the hit.
  976. !
  977. :HITPLAYER
  978.   if player.hp > 0 then
  979.     dec( player.hp );
  980.     if player.hp = 0 then
  981.       writeln( player.name, " has died of ", s0, "!" );
  982.     elsif player.hp = 1 then
  983.       writeln( player.name, " has fainted from ", s0, "!" );
  984.     else
  985.       writeln( player.name, " weakens!" );
  986.     endif;
  987.   endif;
  988.   return;
  989.  
  990. !------------------------------------------------------------------------!
  991. !
  992. ! SUBROUTINE: M1_INVOKE
  993. !
  994. ! Type 1 Magic - Affects the person invoking the magic..
  995. !
  996. ! This code is equivalent to the one in OBJECT.SCR.  When resting, 
  997. ! rings and amulets that have magical properties will re-invoke their
  998. ! effect when you wake up.
  999. !
  1000. !------------------------------------------------------------------------!
  1001. :M1_INVOKE
  1002. !------------------------------------------------------------------------!
  1003.  
  1004.   if curritem.cursed then
  1005.     if curritem.permanent then
  1006.       writeln( "WARNING: Cursed Item with permanent effect not recommended!");
  1007.       curritem.permanent = FALSE;
  1008.     endif;
  1009.   endif;
  1010.  
  1011.   if curritem.charges < 255 then
  1012.     dec(curritem.charges);  ! 255 means forever !
  1013.   endif;
  1014.  
  1015.   on curritem.class goto
  1016.     M1_NONE,    M1_CURE,    M1_HEAL,    M1_POISON,    M1_RESTORE,
  1017.     M1_STR,     M1_DEX,     M1_SPD,     M1_AIM,       M1_AC,
  1018.     M1_HP,      M1_IQ,      M1_PWR;
  1019.  
  1020. :M1_NONE
  1021.   return;
  1022.  
  1023. :M1_CURE
  1024.   if player.poisoned then
  1025.     player.poisoned = 0;
  1026.     writeln( player.name, " is now cured." );
  1027.   endif;
  1028.   return;
  1029.  
  1030. :M1_HEAL
  1031.   if player.hp > 0 and player.hp < player.mhp then
  1032.     if curritem.units > 0 then
  1033.       L(0) = curritem.units;                   ! always heals the same points !
  1034.     else
  1035.       L(0) = random(player.mhp - player.hp)+1; ! heal a random number of points !
  1036.     endif;
  1037.     if player.hp + L(0) < player.mhp then
  1038.       writeln( player.name, " heals ", L(0), " hit points.." );
  1039.       inc( player.hp, L(0) );
  1040.     else
  1041.       writeln( player.name, " has been completely healed!" );
  1042.       player.hp = player.mhp;
  1043.     endif;
  1044.   endif;
  1045.   return;
  1046.  
  1047. :M1_POISON
  1048.   if NOT player.poisoned then
  1049.     player.poisoned = TRUE;
  1050.     writeln( player.name, " is poisoned!" );
  1051.   endif;
  1052.   return;
  1053.  
  1054. :M1_RESTORE
  1055.   if player.hp < player.mhp then
  1056.     player.hp = player.mhp;
  1057.     writeln( player.name, " is completely healed!" );
  1058.   endif;
  1059.   return;
  1060.  
  1061. :M1_STR
  1062.   if curritem.cursed then
  1063.     player.str = 0;
  1064.   else
  1065.     inc( player.str, curritem.units );
  1066.     if curritem.permanent then
  1067.       inc( player.mstr, curritem.units );
  1068.     endif;
  1069.     writeln( player.name, "'s strength increased by ", curritem.units, "!" );
  1070.   endif;
  1071.   return;
  1072.  
  1073. :M1_DEX
  1074.   if curritem.cursed then
  1075.     player.dex = 0;
  1076.   else
  1077.     inc( player.dex, curritem.units );
  1078.     if curritem.permanent then
  1079.       inc( player.mdex, curritem.units );
  1080.     endif;
  1081.     writeln( player.name, "'s dexterity increased by ", curritem.units, "!" );
  1082.   endif;
  1083.   return;
  1084.  
  1085. :M1_SPD
  1086.   if curritem.cursed then
  1087.     player.spd = 0;
  1088.   else
  1089.     inc( player.spd, curritem.units );
  1090.     if curritem.permanent then
  1091.       inc( player.mspd, curritem.units );
  1092.     endif;
  1093.     writeln( player.name, "'s speed increased by ", curritem.units, "!" );
  1094.   endif;
  1095.   return;
  1096.  
  1097. :M1_AIM
  1098.   if curritem.cursed then
  1099.     player.aim = 0;
  1100.   else
  1101.     inc( player.aim, curritem.units );
  1102.     if curritem.permanent then
  1103.       inc( player.maim, curritem.units );
  1104.     endif;
  1105.     writeln( player.name, "'s aim increased by ", curritem.units, "!" );
  1106.   endif;
  1107.   return;
  1108.  
  1109. :M1_AC
  1110.   if curritem.cursed then
  1111.     player.ac = 0;
  1112.   else
  1113.     inc( player.ac, curritem.units );
  1114.     if curritem.permanent then
  1115.       inc( player.mac, curritem.units );
  1116.     endif;
  1117.     writeln( player.name, "'s armor class increased by ", curritem.units, "!" );
  1118.   endif;
  1119.   return;
  1120.  
  1121. :M1_HP
  1122.   if curritem.cursed then
  1123.     player.hp = player.hp / 3 + 1;
  1124.   else
  1125.     inc( player.hp, curritem.units );
  1126.     if curritem.permanent then
  1127.       inc( player.mhp, curritem.units );
  1128.     endif;
  1129.     writeln( player.name, "'s hit points increased by ", curritem.units, "!" );
  1130.   endif;
  1131.   return;
  1132.  
  1133. :M1_IQ
  1134.   if curritem.cursed then
  1135.     player.iq = 0;
  1136.   else
  1137.     inc( player.iq, curritem.units );
  1138.     if curritem.permanent then
  1139.       inc( player.miq, curritem.units );
  1140.     endif;
  1141.     writeln( player.name, "'s i.q. increased by ", curritem.units, "!" );
  1142.   endif;
  1143.   return;
  1144.  
  1145. :M1_PWR
  1146.   if player.class = ELF or player.class = WIZARD then
  1147.     if curritem.cursed then
  1148.       player.pwr = 0;
  1149.     else
  1150.       inc( player.pwr, curritem.units );
  1151.       if curritem.permanent then
  1152.         inc( player.mpwr, curritem.units );
  1153.       endif;
  1154.       writeln( player.name, "'s power increased by ", curritem.units, "!" );
  1155.     endif;
  1156.   else
  1157.     write( player.name, " has a headache all night long.." );
  1158.     if player.hp < 3 then
  1159.       writeln( " and dies!" );
  1160.       player.hp = 0;
  1161.     else
  1162.       writeln;
  1163.       dec( player.hp, 2 );
  1164.     endif;
  1165.   endif;
  1166.   return;
  1167.  
  1168. !-----------------------------------------------------------------------!
  1169. ! Allow ONE minute of time to go bye in the game's clock                !
  1170. !-----------------------------------------------------------------------!
  1171. :CLOCK_TICK
  1172.  
  1173.   if minute < MinutesInAnHour - 1 then
  1174.     inc( minute );
  1175.   else
  1176.     minute = 0;
  1177.     if hour < HoursInADay - 1 then
  1178.       inc( hour );
  1179.     else
  1180.       hour = 0;
  1181.       if day < DaysInAMonth - 1 then
  1182.         inc( day );
  1183.       else
  1184.         day = 0;
  1185.         if month < MonthsInAYear - 1 then
  1186.           inc( month );
  1187.         else
  1188.           month = 0;
  1189.           inc( year );
  1190.         endif;
  1191.       endif;
  1192.       if hour = sunrise then
  1193.         writeln( "The sun rises in the east. " );
  1194.         ! gosub DAYNIGHT;
  1195.       elsif hour = sunset then
  1196.         writeln( "The sun sets in the west. " );
  1197.         ! gosub DAYNIGHT;
  1198.       endif;
  1199.     endif;
  1200.   endif;
  1201.   return;
  1202.  
  1203. !-----------------------------------------------------------------------!
  1204. ! Print the current time                                                !
  1205. !-----------------------------------------------------------------------!
  1206. :CLOCK_PRINT
  1207.  
  1208.   L1 = HoursInADay / 2; ! Noon !
  1209.   if hour > L1 then
  1210.     if minute = 0 then
  1211.       writeln( "It's ", hour - L1, "pm" );
  1212.     elsif minute < 10 then
  1213.       writeln( "It's ", hour - L1, ":0", minute, "pm" );
  1214.     else
  1215.       writeln( "It's ", hour - L1, ":", minute, "pm" );
  1216.     endif;
  1217.   elsif hour = 0 then
  1218.     writeln( "It's midnight" );
  1219.   elsif hour = L1 then
  1220.     writeln( "It's noon" );
  1221.   else
  1222.     if minute = 0 then
  1223.       writeln( "It's ", hour, "am" );
  1224.     elsif minute < 10 then
  1225.       writeln( "It's ", hour, ":0", minute, "am" );
  1226.     else
  1227.       writeln( "It's ", hour, ":", minute, "am" );
  1228.     endif;
  1229.   endif;
  1230.   return;
  1231. !
  1232.  
  1233. !:DAYNIGHT
  1234. !
  1235. ! Ideally, we should reflect sunrise and sunset by some visual
  1236. ! change in the game.  For example:
  1237. !
  1238. ! If we wanted to create a "daylight"/"night-type" effect, we have
  1239. ! two options. One, create two landscape sets that are identical
  1240. ! except one uses darker colors (you really need 256 colors for 
  1241. ! this), as follows:
  1242. !
  1243. ! if world.type = OUTDOORS then
  1244. !   if hour = sunrise then
  1245. !     world.landscape = 0;
  1246. !   elsif hour = sunset then
  1247. !     world.landscape = 1;
  1248. !   endif;
  1249. ! endif;
  1250. ! return;
  1251. !
  1252. ! The second one is to have a second PALETTE of colors, which
  1253. ! are darker than the standard palette.  You can then just
  1254. ! change the palette
  1255. !
  1256. ! if hours = sunset then loadpalette( "NIGHT.PAL" );
  1257. ! elsif hour = sunrise then loadpalette( "DAY.PAL" );
  1258. ! return;
  1259. !
  1260. ! However, I did not implement 'loadpalette()' yet, so this last
  1261. ! option is not possible right now. :)
  1262. !
  1263.  
  1264. !------------------------------------------------------
  1265. ! Attack an NPC
  1266. !------------------------------------------------------
  1267.  
  1268. :ATTACK_NPC
  1269.   ! L3 contains distance to current npc per LOCATE command !
  1270.   ! L4 the weapon class (blunt, missile, etc)
  1271.   ! L5 the range (distance) you can reach with this weapon
  1272.   ! L6 is non-zero if type of ammo that is needed by the weapon
  1273.   ! L7 is the damage points done
  1274.   if player.weapon.count then 
  1275.     L4 = player.weapon.class;
  1276.     L5 = player.weapon.range;
  1277.     L6 = player.weapon.ammoneeded;
  1278.     L7 = player.weapon.damage;
  1279.   else
  1280.     L4 = BLUNT;
  1281.     L5 = 1;
  1282.     L6 = 0;
  1283.     L7 = 1;
  1284.   endif;
  1285.   if L4 = MISSILE then
  1286.     for L10 = 0 to 15 do
  1287.       setbp( player, L10 );
  1288.       if player.bp.count then
  1289.         if player.bp.type = AMMO and player.bp.ammotype = L6 then
  1290.           if player.bp.count < 255 then
  1291.             dec(player.bp.count);          ! Count of 255 means it never ends? !
  1292.           endif;
  1293.           L5 = max( L5, player.bp.range ); ! Use ammo's range if higher !
  1294.           inc( L7, player.bp.damage );     ! If ammunition causes extra damage !
  1295.           L6 = L10;                        ! Keep AMMO's BP here !
  1296.           goto FOUND_AMMO;
  1297.         endif;
  1298.       endif;
  1299.     endfor;
  1300.     writeln( "Out of ammo! Using hands!" );
  1301.     L4 = BLUNT;
  1302.     L5 = 1;
  1303.     L6 = 0;
  1304.     L7 = 1;
  1305. :FOUND_AMMO
  1306.   endif;
  1307.   if L5 < L3 then
  1308.     writeln( "You have to get closer!" );
  1309.     stop;
  1310.   endif;
  1311.  
  1312.   ! HERE I COULD 'RANDOMIZE' THE DAMAGE, BUT I'LL LET IT BE CONSTANT FOR NOW !
  1313.  
  1314.   ! For contact weapons, STRENGTH increases damage !
  1315.   if L4 = BLUNT or L4 = EDGED then
  1316.     inc( L7, adjustments( player.str ) );
  1317.   endif;
  1318.  
  1319.   ! Now, we have to figure out if we missed !
  1320.   if L4 = MISSILE then
  1321.     ! For missile weapon, hit 5 out of 10, adjusted by AIM !
  1322.     if random( 10 ) + adjustments( player.aim ) < 5 then
  1323.       writeln( player.name, " missed.." );
  1324.       voice( "BadAim", 1000 );
  1325.     else
  1326.       gosub HIT_NPC;
  1327.     endif;
  1328.   else
  1329.     ! For non-missile weapon, hit 7 out of 10 adjusted up by the
  1330.     ! player's dexterity and down by the NPC's dexterity
  1331.     if random(10) + adjustments(player.dex) - adjustments(npc.dex) < 3 then
  1332.       writeln( player.name, " missed.." );
  1333.       voice( "Swish", 1000 );
  1334.     else
  1335.       gosub HIT_NPC;
  1336.     endif;
  1337.   endif;
  1338.   stop;
  1339.  
  1340. :HIT_NPC
  1341.  
  1342.   L7 = max( L7, 1 ); ! At least one HP of damage !
  1343.   if npc.hp > 1 and npc.ac > 0 then ! Armor Class protects the NPC !
  1344.     L8 = random( npc.ac+1 ); ! Absorb 0 to npc.ac damage points !
  1345.     if L8 >= L7 then
  1346.       writeln( npc.type, "'s armor absorbs the impact!" );
  1347.       voice( "Clank", 1000 );
  1348.       return;
  1349.     endif;
  1350.     dec( L7, L8 ); ! Reduce damage by L8 amount !
  1351.   endif;
  1352.  
  1353.   ! Fast PLAYERS get to hit more than once !
  1354.   if player.spd > npc.spd then
  1355.     L9 = (player.spd - npc.spd) / 10 + 1;
  1356.   else 
  1357.     L9 = 1;
  1358.   endif;
  1359.   while L9 > 0 and npc.count do
  1360.     if npc.hp > L7 then
  1361.       write( npc.type, " hit!" );
  1362.       dec( npc.hp, L7 );
  1363.       on random(3) gosub :V1, :V2, :V3;
  1364.     else
  1365.       write( npc.type, " killed!" );
  1366.       voice( "YouKill", 1000 );
  1367.       L7 = npc.hp;
  1368.       ! Now is the perfect time to GENERATE RANDOM TREASURE !
  1369.       gosub TREASURE;
  1370.       npc.count = 0; ! Actually Kill the NPC !
  1371.     endif;
  1372.     writeln( " (", L7, " points)" );
  1373.     inc( player.exp, L7 ); 
  1374.     dec(L9);
  1375.   endwhile;
  1376.  
  1377.   return;
  1378.  
  1379. :V1 voice( "Argh",   1000 ); return;
  1380. :V2 voice( "Ouch",   1000 ); return;
  1381. :V3 voice( "Whoosh", 1000 ); return;
  1382.  
  1383. !------------------------------------
  1384. :TREASURE
  1385. !------------------------------------
  1386. ! Generate random treasure
  1387.  
  1388.   ! First, leave the contents of the NPCs backpack..
  1389.   foreach npc.bp do
  1390.     drop( npc.bp, -npc.count, npc.x, npc.y ); ! Drop a copy of this item
  1391.   endfor;
  1392.  
  1393.   ! Now generate a random treasure
  1394.   on random(4) goto GT_NONE, GT_GOLD, GT_CHEST, GT_SPECIAL;
  1395. :GT_NONE
  1396.   return;
  1397.  
  1398. :GT_GOLD
  1399.   new( object, npc.x, npc.y, GOLDSACK );
  1400.   object.weight = random( player.mhp ) + 1;
  1401.   object.value  = object.weight * 10;
  1402.   return;
  1403.  
  1404. :GT_CHEST
  1405.   new( object, npc.x, npc.y, CHEST );
  1406.   object.class  = NORMAL_CHEST;
  1407.   object.weight = random( player.mhp ) + 1;
  1408.   object.value  = object.weight * 10;
  1409.   object.locktype = random(2); ! 0=None, 1+ = Key !
  1410.   object.traptype = random(3); ! 0=None, 1=Poison, 2+ = Bomb !
  1411.   return;
  1412.  
  1413. :GT_SPECIAL
  1414.   ! AMULET=5,RING=6,POTION=7,SCROLL=8,STAFF=9
  1415.   new( object, npc.x, npc.y, AMULET + random(5) );
  1416.   if object.type = SCROLL or object.type = STAFF then ! SCROLL or STAFF !
  1417.     object.class  = random(15)+1; ! See OBJECT CLASS in DCCTOKEN.DAT !
  1418.   else
  1419.     object.class  = random(12)+1; ! See OBJECT CLASS in DCCTOKEN.DAT !
  1420.   endif;
  1421.   object.weight = 1;
  1422.   if object.type = RING or object.type = AMULET or object.type = STAFF then
  1423.     object.charges = random( player.level ) + 1;
  1424.   endif;
  1425.   if object.type = RING or object.type = AMULET or object.type = POTION then
  1426.     object.units  = random( player.mhp ) + 1;
  1427.     object.permanent = (random(100) = 0); ! One out of 100 !
  1428.   endif;
  1429.   if object.permanent then
  1430.     object.value  = 1000;
  1431.     object.weight =    2;
  1432.   else
  1433.     object.value =   10;
  1434.   endif;
  1435.   return;
  1436.  
  1437. !------------------------------------
  1438. :NEW_LEVEL
  1439. !------------------------------------
  1440.  
  1441.   L10 =   1;  ! Start with level 1
  1442.   L11 = 200;  ! Next level is at 200 
  1443.   while L11 < player.exp do
  1444.     inc( L11, L11 ); ! Each level is TWICE as much as the previous one !
  1445.     inc( L10, 1 );
  1446.   endwhile;
  1447.   if L10 > player.level then    ! New Level !
  1448.     L12 = random( player.level ) + 1;  ! First, give some hit points !
  1449.     write( "New level! ", player.name, " gained ", L12, "hp " );
  1450.     inc( player.level );
  1451.     inc( player.mhp, L12 );     ! Permanent Increase !
  1452.     inc( player.hp, L12 );      ! Reflect the new HP immediatly !
  1453.  
  1454.     ! Now increase one ore more attributes depending on the class !
  1455.     L12 = random(player.level + 1) + 1; ! Start with this many points !
  1456.     if L12 > 5 then
  1457.       L12 = random(10); ! Make more than 5 points 'unlikely' but possible
  1458.     endif;
  1459.     on player.class goto
  1460.       :EX_HUMAN,
  1461.       :EX_ELF,
  1462.       :EX_DWARF,
  1463.       :EX_WIZARD,
  1464.       :EX_ARCHER,
  1465.       :EX_FIGHTER;
  1466.   endif;
  1467.   return; ! No new level !
  1468.  
  1469. :EX_HUMAN  ! Humans and 'unknown'
  1470.     inc( player.mstr, L12 );
  1471.     writeln( "and ", L12, " str." );
  1472.     return;
  1473.  
  1474. :EX_ELF
  1475.     inc( player.miq, L12 + L12 ); ! Elf gains intelligence twice as fast !
  1476.     writeln( "and ", L12, " iq." );
  1477.     return;
  1478.  
  1479. :EX_DWARF
  1480.     L13 = random(L12);
  1481.     inc( player.mstr, L12 - L13 ); ! Dwarf gains some strength !
  1482.     inc( player.mdex, L13 );       ! and some dexterity        !
  1483.     writeln( ", ", L12 - L13, " str and ", L13, " dex." );
  1484.     return;
  1485.  
  1486. :EX_WIZARD
  1487.     inc( player.miq, L12 ); ! Wizards gain intelligence !
  1488.     writeln( "and ", L12, " iq." );
  1489.     return;
  1490.  
  1491. :EX_ARCHER
  1492.     L13 = random(L12);
  1493.     inc( player.maim, L12 - L13 ); ! Dwarf gains some aim !
  1494.     inc( player.mspd, L13 );       ! and some speed       !
  1495.     writeln( ", ", L12 - L13, " aim and ", L13, " speed." );
  1496.     return;
  1497.  
  1498. :EX_FIGHTER
  1499.     inc( L12, random(L12) );       ! Fighters gain strength more quickly !
  1500.     inc( player.mstr, L12 );
  1501.     writeln( "and ", L12, " str." );
  1502.     return;
  1503.  
  1504. !
  1505. ! Look at current bp object
  1506. !
  1507. :DESCRIBE
  1508.   if curritem.picture >= 0 then
  1509.     viewpcx( curritem );
  1510.     if success then
  1511.       pause;
  1512.     endif;
  1513.     paint(window); ! Assumes the picture fits in the window !
  1514.   elsif curritem.type = SIGN or curritem.type = BOOK then
  1515.     readtext( curritem.text );
  1516.     RETURN;
  1517.   endif;
  1518.   write( "You see a ", curritem.name );
  1519.   write( ", Type: ", curritem.type );
  1520. !
  1521. ! The following is a 'cascading if..then..elsif..elsif.....else..endif' 
  1522. ! statement.  It is used here to illustrate it's usefulness.  The same
  1523. ! code could have been written with a 'ON object.type GOTO' statement.
  1524. !
  1525.   if object.type = FOOD or object.type = POTION  then
  1526.     if object.class then
  1527.       write( ", Class: ", object.class );
  1528.       if object.class <> CURE then
  1529.         write( ", Units: ", object.units );
  1530.       endif;
  1531.     endif;
  1532.   elsif object.type = WEAPON then
  1533.     write( ", Class: ", object.class, 
  1534.            ", Hands: ", object.hands, 
  1535.            ", Range: ", object.range, 
  1536.            ", Damage: ", object.damage );
  1537.     if object.ammoneeded then
  1538.       write( ", Needs ammo type: ", object.ammo_type );
  1539.     endif;
  1540.   elsif object.type = AMMO then
  1541.     write( ", Ammo Type: ", object.ammotype );
  1542.     if object.traptype then
  1543.       write( ", Poisoned" );
  1544.     endif;
  1545.     if object.damage then
  1546.       write( ", Extra Damage: ", object.damage );
  1547.     endif;
  1548.   elsif object.type = ARMOR or object.type = SHIELD then
  1549.     write( ", Armor Class: ", object.ac );
  1550.     if object.cursed then
  1551.       write( " Cursed!" );
  1552.     endif;
  1553.   elsif object.type = AMULET or object.type = RING or object.type = GEMS then
  1554.     if object.class then
  1555.       write( ", Class: ", object.class );
  1556.       write( ", Charges: ", object.charges );
  1557.       if object.class <> CURE then
  1558.         write( ", Units: ", object.units );
  1559.         if object.permanent then
  1560.           write( ", Permanent!" );
  1561.         else
  1562.           write( ", Temporary" );
  1563.         endif;
  1564.       endif;
  1565.       if object.cursed then
  1566.         write( ", Cursed!" );
  1567.       endif;
  1568.     endif;
  1569.   elsif object.type = SCROLL then
  1570.     write( ", Class: ", object.class );
  1571.   elsif object.type = STAFF then
  1572.     write( ", Class: ", object.class, ", Charges: ", object.charges );
  1573.   elsif object.type = CHEST then
  1574.     if object.locktype then
  1575.       write( ", Locked!" );
  1576.       if object.traptype = 0 then
  1577.         write( ", no traps" );
  1578.       elsif object.traptype = 1 then
  1579.         write( ", poison trap" );
  1580.       else
  1581.         write( ", bomb damage: ", object.traptype );
  1582.       endif;
  1583.     endif;
  1584. ! elsif object.type = KEYS     then
  1585. !   nothing special about it
  1586. ! elsif object.type = BOOK     then
  1587. !   nothing special about it
  1588. ! elsif object.type = GOLDSACK then
  1589. !   nothing special about it
  1590. ! elsif object.type = TORCH    then
  1591. !   nothing special about it
  1592. ! elsif object.type = LANTERN  then
  1593. !   nothing special about it
  1594. ! elsif object.type = ROPE     then
  1595. !   nothing special about it
  1596. ! elsif object.type = HOOKS    then
  1597. !   nothing special about it
  1598. ! elsif object.type = MIRROR   then
  1599. !   nothing special about it
  1600. ! elsif object.type = SIGN     then
  1601. !   nothing special about it
  1602.   elsif object.type = VEHICLE then
  1603.     write( ", Class: ", object.class );
  1604. ! else
  1605. !   user defined type?
  1606.   endif;
  1607.   if object.weight > 1 and object.weight < 256 then
  1608.     write( ", Weight: ", object.weight );
  1609.   endif;
  1610.   writeln( "." );
  1611.   return;
  1612.  
  1613. !
  1614. ! MOVING THE CHARACTERS
  1615. !
  1616.  
  1617. :MOVE_UP
  1618.   L3 =  0; L4 = -1; goto DO_MOVE;
  1619.  
  1620. :MOVE_DN
  1621.   L3 =  0; L4 =  1; goto DO_MOVE;
  1622.  
  1623. :MOVE_LF
  1624.   L3 = -1; L4 =  0; goto DO_MOVE;
  1625.  
  1626. :MOVE_RT
  1627.   L3 =  1; L4 =  0; goto DO_MOVE;
  1628.  
  1629. :MOVE_UL
  1630.   L3 = -1; L4 = -1; goto DO_MOVE;
  1631.     
  1632. :MOVE_DL
  1633.   L3 = -1; L4 =  1; goto DO_MOVE;
  1634.  
  1635. :MOVE_UR
  1636.   L3 =  1; L4 = -1; goto DO_MOVE;
  1637.  
  1638. :MOVE_DR
  1639.   L3 =  1; L4 =  1; goto DO_MOVE;
  1640.  
  1641. :DO_MOVE
  1642.   L0 = player.x + L3;
  1643.   L1 = player.y + L4;
  1644.   if world.wrap_around then
  1645.     if L0 < 0 then
  1646.       gosub NOTFIGHTING;
  1647.       L0 = world.x - 1;
  1648.     elsif L0 >= world.x then
  1649.       gosub NOTFIGHTING;
  1650.       L0 = 0;
  1651.     endif;
  1652.     if L1 < 0 then
  1653.       gosub NOTFIGHTING;
  1654.       L1 = world.y - 1;
  1655.     elsif L1 >= world.y then
  1656.       gosub NOTFIGHTING;
  1657.       L1 = 0;
  1658.     endif;
  1659.   else
  1660.     if L0 < 0 or L0 >= world.x or L1 < 0 or L1 >= world.y then
  1661.       gosub NOTFIGHTING;
  1662.       writeln( "Do you wan't to leave ", world.name, "?" );
  1663.       if select( "Yes", "No" ) = 0 then
  1664.         world.door = world.edge_door;
  1665.         runscript( WORLD, "WORLDDEF", EXIT );
  1666.         ! 
  1667.         ! NOTE: We could just run "enter( world.edge_door );" instead
  1668.         ! of the above two lines.  The difference is that when you
  1669.         ! run ENTER( door ), the driver does NOT call the @EXIT
  1670.         ! routine in the current world.  A minor but important
  1671.         ! difference. The reason for this, is that the behaviour of
  1672.         ! ENTERING A WORLD (i.e. load the world, call script at @GET,
  1673.         ! call script at @ENTER) is a feature of the driver, but
  1674.         ! the @EXIT entry point is handled entirely by the scripts
  1675.         ! themselves. If you don't want to take any action when you
  1676.         ! exit a world, you can change the above two lines to a 
  1677.         ! simple call to the ENTER() function.
  1678.         !
  1679.       endif;
  1680.       stats(-1);
  1681.       STOP; 
  1682.     endif;
  1683.   endif;
  1684.   !
  1685.   ! Use a LOOP through all the NPCs, to see if there is one
  1686.   ! standing at that spot or a guard NEAR the spot
  1687.   !
  1688.   L2 = locate( npc, L0, L1 ); ! Is there an object at L0,L1? !
  1689.   if L2 >= 0 then
  1690.     writeln( "There is someone standing in your way!" );
  1691.     STOP;
  1692.   endif;
  1693.   ! Check for guards !
  1694.   ! The following loop works fine, but it selects every NPC in the 
  1695.   ! world, loading it's statistics record into memory and causing
  1696.   ! a disk access. While the game driver has a small cache of stat
  1697.   ! records, it still is better to avoid a 'foreach' loop on the
  1698.   ! NPCs in the control script. Note that you can use foreach on
  1699.   ! the players and objects because they are already in memory.
  1700.   ! -> THIS WORKS, BUT CAUSES UNNECESARY DISK ACCESS
  1701.   !   foreach NPC do
  1702.   !     if npc.type = GUARD then
  1703.   !       if abs(npc.x - L0) < 2 and abs(npc.y - L1) < 2 then
  1704.   !         writeln( "There is a GUARD there!" );
  1705.   !         STOP;
  1706.   !       endif;
  1707.   !     endif;
  1708.   !   endfor;
  1709.   ! The following is better. It uses a new feature of the LOCATE
  1710.   ! command. If you provide an X,Y coordinate, it looks for the
  1711.   ! specified NPC or OBJECT at the given location. It only causes
  1712.   ! a disk access if there is an NPC at that location, and that
  1713.   ! NPC has a much better chance of having it's record cached.
  1714.   ! -> MUCH BETTER:
  1715.     if L3 then ! Moving on X !
  1716.       L2 = locate( npc, L0+L3, L1 );
  1717.       if success then gosub check_guard; endif;
  1718.       L2 = locate( npc, L0+L3, L1+1 );
  1719.       if success then gosub check_guard; endif;
  1720.       L2 = locate( npc, L0+L3, L1-1 );
  1721.       if success then gosub check_guard; endif;
  1722.     endif;
  1723.     if L4 then ! Moving on Y !
  1724.       L2 = locate( npc, L0  , L1+L4 );
  1725.       if success then gosub check_guard; endif;
  1726.       L2 = locate( npc, L0+1, L1+L4 );
  1727.       if success then gosub check_guard; endif;
  1728.       L2 = locate( npc, L0-1, L1+L4 );
  1729.       if success then gosub check_guard; endif;
  1730.     endif;
  1731.   !
  1732.   ! No find if there are any OBJECTS at the X, Y location.
  1733.   !
  1734.   L2 = locate( object, L0, L1 ); ! Is there an object at L0,L1? !
  1735.   if L2 >= 0 then
  1736.     ! Check for locked doors
  1737.     if object.type = DOOR and object.locktype > 0 then
  1738.       writeln("The door is locked!" );
  1739.       STOP;
  1740.     endif;
  1741.     ! Check for fences and things, both of which we should not
  1742.     ! be able to walk over.
  1743.     if object.type = FENCE or object.type = THING then
  1744.       writeln( "There is a ", object.name, " in your way" );
  1745.       STOP;
  1746.     endif;
  1747.   endif;
  1748.   !
  1749.   ! Now check the world's density and see if we can walk over it
  1750.   ! considering the type of landscape and the vehicle (if any)
  1751.   !
  1752.   L2 = world.density(L0,L1);
  1753.   if L2 = WALL or L2 = LOCKED_DOOR or L2 = HIDDEN_DOOR then
  1754.     STOP;   ! Can't Move !
  1755.   endif;
  1756.   on group.vehicle.class goto
  1757.     CHK_WALK, CHK_MOUNT, CHK_ATV, CHK_LFLY, CHK_MFLY, CHK_HFLY, CHK_RAFT, CHK_BOAT;
  1758.   ! Anything else, don't allow the move !
  1759.   STOP;
  1760. ! -- ON WATER -- !
  1761. :CHK_RAFT
  1762.   if L2 = LOW_WATER or L2 = ROUGH_WATER goto CHK_OK;
  1763.   STOP;
  1764. :CHK_BOAT
  1765.   if L2 = DEEP_WATER goto CHK_OK;
  1766.   STOP;
  1767. ! -- BY AIR -- !
  1768. :CHK_LFLY
  1769.   if L2 = DEEP_WATER then STOP; endif;
  1770.   ! Drop Through !
  1771. :CHK_MFLY
  1772.   if L2 = VERY_HIGH  then STOP; endif;
  1773.   ! Drop Through !
  1774. :CHK_HFLY
  1775.   goto CHK_OK;
  1776. :CHK_WALK
  1777.   if L2 = FLAT or L2 = DESERT or L2 = SWAMP goto CHK_OK;
  1778.   if L2 = ROUGH      and random(3) <> 0 or
  1779.      L2 = VERY_ROUGH and random(3)  = 0     goto CHK_OK;
  1780.   if L2 = ROUGH or L2 = VERY_ROUGH then
  1781.     writeln( "Rough terrain.." );
  1782.   endif;
  1783.   ! Anything else, don't allow the move !
  1784.   STOP;
  1785. :CHK_MOUNT
  1786.   if L2 = FLAT                          or
  1787.      L2 = ROUGH                         or
  1788.      L2 = VERY_ROUGH and random(3) <> 0 then ! 2 out of 3 ! 
  1789.     goto CHK_OK;
  1790.   endif;
  1791.   if L2 = VERY_ROUGH then
  1792.     writeln( "Very rough terrain.." );
  1793.   endif;
  1794.   STOP;
  1795. :CHK_ATV
  1796.   if L2 = FLAT or L2 = ROUGH or L2 = VERY_ROUGH or L2 = LOW_WATER then
  1797.     goto CHK_OK; ! All Terrain Vehicle !
  1798.   endif;
  1799.   ! Anything else, don't allow the move !
  1800.   STOP;
  1801.  
  1802. :CHECK_GUARD
  1803.   !
  1804.   ! From GUARD.SCR, npc.v1 = 1 means you have given the password to the
  1805.   ! guard, so you can pass.  npc.v1 = 2 means you have given a BRIBE to
  1806.   ! the guard, so you can also pass.
  1807.   !
  1808.   if npc.type = GUARD and npc.v1 = 0 then
  1809. writeln( "npc.name=",npc.name,", npc.v0=",npc.v0," npc.v1=",npc.v1);
  1810.     writeln( "There is a GUARD there!" );
  1811.     STOP;
  1812.   endif;
  1813.   return;
  1814. :CHK_OK
  1815.   ! Go Ahead and Move
  1816.   if fighting then
  1817.     if group.vehicle.count then ! Inside a vehicle !
  1818.       group.x = L0; group.y = L1;
  1819.     else
  1820.       player.x = L0; player.y = L1;
  1821.     endif;
  1822.   else
  1823.     group.x  = L0; group.y  = L1;
  1824.     ! Check for Trap doors !
  1825.     if L0 > 0 and L1 > 0 then
  1826.       for L5 = 0 to 31 do
  1827.         if L0 = world.doorx(L5) and L1 = world.doory(L5) then
  1828.           if world.trapdoorswitch(L5) then
  1829.             world.door = L5; ! Use this door !
  1830.             runscript( WORLD, "WORLDDEF", EXIT );
  1831.           endif;
  1832.         endif;
  1833.       endfor;
  1834.     endif;
  1835.   endif;
  1836.   STOP;
  1837.  
  1838. :NOTFIGHTING
  1839.   if fighting then
  1840.     writeln( "You can't leave during a fight.." );
  1841.     stop;
  1842.   endif;
  1843.   return;
  1844.  
  1845. :FKEY1
  1846. ! Help !
  1847.   writeln( "The following commands are defined:" );
  1848.   write( "A)ttack, ");
  1849.   write( "C)amp, ");
  1850.   write( "D)rop, ");
  1851.   write( "E)nter, ");
  1852.   write( "G)et, ");
  1853.   write( "I)nventory, ");
  1854.   write( "L)ook, ");
  1855.   write( "iN)voike, ");
  1856.   write( "Q)uaff (eat or drink), ");
  1857.   write( "R)emove, ");
  1858.   write( "S)pell, ");
  1859.   write( "T)alk, ");
  1860.   write( "U)se, ");
  1861.   write( "V)acate, ");
  1862.   write( "W)ield/Wear, ");
  1863.   write( "eX)it, ");
  1864.   write( "Z)ap (with staff),");
  1865.   write( "F1=Help, ", "F2=Save, ", "F3=Sound, ", "F4=Restore, ",
  1866.          "F6=Restart, ", "F10=Exit" );
  1867.   writeln;
  1868.   STOP;
  1869.  
  1870. :FKEY2
  1871.   L0 = getnum( "Save in what slot?", 0, 999 );
  1872.   if L0 >= 0 then
  1873.     save( L0 );
  1874.     stop;
  1875.   endif;
  1876.   continue;
  1877.  
  1878. :FKEY3
  1879.   sound = not sound;
  1880.   if sound then
  1881.     writeln( "Sound is now on!" );
  1882.   else
  1883.     writeln( "Sound is now off!" );
  1884.   endif;
  1885.   stop;
  1886.  
  1887. :FKEY4
  1888.   L0 = getnum( "Restore from what slot?", 1, 999 );
  1889.   if L0 > 0 then
  1890.     restore( L0 );
  1891.     writeln( "RESTORE OF SLOT ", L0, " FAILED!" );
  1892.   endif;
  1893.   stop;
  1894.  
  1895. :FKEY5
  1896.   stop;
  1897.  
  1898. :FKEY6
  1899.   writeln( "Do you really want to RESTART?" );
  1900.   L0 = select( "Yes", "No" );
  1901.   if L0 = 0 then
  1902.     restart;
  1903.     writeln( "RESTART FAILED!" );
  1904.   endif;
  1905.   stats(-1);
  1906.   stop;
  1907.  
  1908. :FKEY7
  1909.   foreach player do
  1910.     player.level = 10;
  1911.   endfor;
  1912.   stop;
  1913.  
  1914. :FKEY8
  1915.   savepcx( "SAVESCRN.PCX" );
  1916.   stop;
  1917.  
  1918. :FKEY9
  1919.   runscript( "TEST", 0 );
  1920.   stop;
  1921.  
  1922. :FKEY10
  1923.   if fighting then
  1924.     writeln( "Press ESCape to stop the fight, then F10 to exit!" );
  1925.     stop;
  1926.   endif;
  1927.   writeln( "See you later..." );
  1928.   save(0);
  1929.   end_game;
  1930.  
  1931.